package com.atguigu.admin.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.atguigu.admin.mapper.SysMenuMapper;
import com.atguigu.admin.model.entity.SysMenu;
import com.atguigu.admin.model.entity.SysRoleMenu;
import com.atguigu.admin.model.vo.AssginMenuVo;
import com.atguigu.admin.model.vo.RouterVo;
import com.atguigu.admin.service.SysMenuService;
import com.atguigu.admin.service.SysRoleMenuService;
import com.atguigu.admin.utils.RouterUtils;
import com.atguigu.admin.utils.TreeUtils;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.core.execption.GuiguException;
import com.atguigu.security.utils.SecurityUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2022-10-28
 */
@Transactional(rollbackFor = Exception.class)
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public List<RouterVo> getUserMenuList(Long userId) {
        //超级管理员admin账号id为：1
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1) {
            sysMenuList = baseMapper.selectList(new QueryWrapper<SysMenu>()
                    .eq("status", 1)
                    .orderByAsc("sort_value"));
        } else {
            sysMenuList = baseMapper.findListByUserId(userId);
        }
        //构建树形数据
        List<Tree<Long>> sysMenuTreeList = buildTree(sysMenuList);

        //构建路由
        return RouterUtils.buildRoutersByTree(sysMenuTreeList);
    }

    @Override
    public List<String> getUserPermsList(Long userId) {
        //超级管理员admin账号id为：1
        List<SysMenu> sysMenuList = null;
        if (SecurityUtil.isAdmin(userId)) {
            sysMenuList = baseMapper.selectList(new QueryWrapper<SysMenu>().eq("status", 1));
        } else {
            sysMenuList = baseMapper.findListByUserId(userId);
        }
        //创建返回的集合
        return sysMenuList.stream()
                .filter(sysMenu -> sysMenu.getType() == 2)
                .map(SysMenu::getPerms)
                .collect(Collectors.toList());
    }


    //@Override
    //public List<SysMenu> findNodes() {
    //    // 全部权限列表
    //    List<SysMenu> sysMenuList = this.list();
    //    if (CollectionUtils.isEmpty(sysMenuList)) {
    //        return Collections.emptyList();
    //    }
    //    return MenuUtils.bulidTree(sysMenuList);
    //}

    @Override
    public List<Tree<Long>> findNodes() {
        List<SysMenu> sysMenuList = this.list();
        if (CollectionUtils.isEmpty(sysMenuList)) {
            return Collections.emptyList();
        }
        return buildTree(sysMenuList);
    }

    private List<Tree<Long>> buildTree(List<SysMenu> sysMenuList) {
        TreeNodeConfig treeNodeConfig = TreeUtils.getTreeNodeConfig();
        //转换器 "0" - 最顶层父id值 一般为0之类  nodeList – 源数据集合
        return TreeUtil.build(sysMenuList, 0L, treeNodeConfig,
                // treeNode – 源数据实体
                // tree – 树节点实体
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(treeNode.getSortValue());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("status", treeNode.getStatus());
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("creatTime", treeNode.getCreateTime());
                    tree.putExtra("sortValue", treeNode.getSortValue());
                    tree.putExtra("component", treeNode.getComponent());
                    tree.putExtra("perms", treeNode.getPerms());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.putExtra("select", treeNode.isSelect());
                    tree.putExtra("origin", treeNode);
                }
        );
    }

    private void fillTreeColumn(SysMenu treeNode, Tree<Long> tree) {

    }

    @Override
    public boolean removeMenuById(Long id) {
        // 判断parent_id是要删除的id的菜单数量，如果为0就表示没有子菜单
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<SysMenu>().eq("parent_id", id);
        int count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new GuiguException(ResultCodeEnum.NODE_ERROR);
        }
        return baseMapper.deleteById(id) > 0;
    }

    @Override
    public List<Tree<Long>> findSysMenuByRoleId(Long roleId) {
        // 所有状态为1的数据
        List<SysMenu> menuList = baseMapper.selectList(new QueryWrapper<SysMenu>().eq("status", 1));
        // 根据角色id查询
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        //获取该角色已分配的所有权限id
        List<Long> roleMenuIds = new ArrayList<>();
        for (SysRoleMenu roleMenu : roleMenus) {
            roleMenuIds.add(roleMenu.getMenuId());
        }
        // 遍历所有权限列表
        for (SysMenu sysMenu : menuList) {
            // 设置该权限已分配
            sysMenu.setSelect(roleMenuIds.contains(sysMenu.getId()));
        }
        // 将权限列表转为权限树返回
        return buildTree(menuList);
    }

    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        // 删除已分配权限
        Long roleId = assginMenuVo.getRoleId();
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        // 遍历所有已选择的权限id
        List<SysRoleMenu> insertList = new ArrayList<>();
        for (Long menuId : assginMenuVo.getMenuIdList()) {
            if (menuId != null) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenu.setRoleId(roleId);
                insertList.add(sysRoleMenu);
            }
        }
        sysRoleMenuService.saveBatch(insertList);
    }
}
